home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / minix / update~4.z / update~4 / lib_stdio_notused_vfprintf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-06  |  6.9 KB  |  337 lines

  1. /*            v f p r i n t f
  2.  *
  3.  * This routine provides the same functionality as fprintf
  4.  * except that it uses varargs.h.
  5.  *
  6.  * In this implementation, this routine is basis for all the
  7.  * formatted output routines. printf, fprintf, and sprintf
  8.  * are all defined in terms of vfprintf.
  9.  *
  10.  * The user is referred to the manual page for a full
  11.  * description of the formats available.
  12.  *
  13.  * The function returns the number of bytes generated, or
  14.  * EOF in the case of an error.
  15.  *
  16.  * Patchlevel 1.0
  17.  *
  18.  * Edit History:
  19.  * 03-Sep-1989    Use PUTC() for faster printf processing. Unroll
  20.  *        formatting loops.
  21.  */
  22.  
  23. #include "stdiolib.h"
  24.  
  25. /*LINTLIBRARY*/
  26.  
  27. #define MINBITS        3        /* least bits required --- octal */
  28. #define MAXPREFIX    3        /* overhead for prefix */
  29.  
  30. #define MAXDIGITS    ((sizeof(long)+MINBITS-1)/MINBITS*MINBITS)
  31. #define VBUFFERSIZE    MAXDIGITS+MAXPREFIX
  32.  
  33. #define OPTIONAL(p,c,f,v)    if(*(p)==(c)){(f)=(v);(p)++;}
  34.  
  35. /* Get an integer argument
  36.  *
  37.  * Scan the string beginning at the point indicated for an
  38.  * integer argument. If a '*' is found, the argument pointer
  39.  * is used to retrieve a remote integer.
  40.  */
  41.  
  42. static int integer(p, ap)
  43.  
  44. char **p;                /* pointer to string pointer */
  45. va_list *ap;                /* pointer to argument list */
  46.  
  47. {
  48.   char *cp;                /* character pointer */
  49.   int v;                /* return value */
  50.  
  51.   cp = *p;
  52.  
  53.   if (*cp == '*') {
  54.     v = va_arg(*ap, int);
  55.     cp++;
  56.   }
  57.   else {
  58.     for (v = 0; *cp >= '0' && *cp <= '9'; ) {
  59.       v *= 10;
  60.       v += (*cp++ - '0');
  61.     }
  62.   }
  63.   *p = cp;
  64.   return v;
  65. }
  66.  
  67. int vfprintf(fp, fmt, args)
  68.  
  69. FILE *fp;                /* stream for output */
  70. char *fmt;                /* format for output */
  71. va_list args;                /* argument list */
  72.  
  73. {
  74.   char buf[VBUFFERSIZE];        /* workspace */
  75.   int bytes;                /* bytes output */
  76.  
  77.   char *p, *q;                /* pointers into workspace */
  78.  
  79.   char leftjustify;            /* left justify */
  80.   char showsign;            /* display a sign */
  81.   char blankprefix;            /* prefix with blank */
  82.   char alternate;            /* alternate format */
  83.  
  84.   char zerofill;            /* fill with zeros */
  85.   char flush;                /* need to flush afterwards */
  86.   int width;                /* field width */
  87.  
  88.   int precision;            /* precision */
  89.  
  90.   char longflag;            /* number is long */
  91.  
  92.   char capitals;            /* capitals */
  93.   char backward;            /* direction for scan */
  94.  
  95.   char prefix;                /* number has prefix -/ /+ */
  96.  
  97.   unsigned int radix;            /* radix for conversion */
  98.   char sign;                /* conversion is signed */
  99.   char negative;            /* number is negative */
  100.   long vl;                /* conversion temporary */
  101.   unsigned short vs;            /* conversion temporary */
  102.   char shortint;            /* short or long */
  103.   int c;                /* conversion temporary */
  104.   int length;                /* raw length of output */
  105.  
  106.   for (flush = bytes = 0; *fmt != 0; ) {
  107.  
  108. /* Look for the next format field */
  109.     for (p = fmt; ; ) {
  110.       if (*p == 0 || *p == '%') break;
  111.       if (PUTC(*p++, fp) == '\n') flush = 1;
  112.       if (*p == 0 || *p == '%') break;
  113.       if (PUTC(*p++, fp) == '\n') flush = 1;
  114.     }
  115.     bytes += p - fmt;
  116.     if (*p == 0) break;
  117.     fmt = p + 1;
  118.  
  119. /* Initialise conversion variables */
  120.     p = q = buf;
  121.  
  122.     leftjustify = 0;
  123.     showsign    = 0;
  124.     blankprefix = 0;
  125.     alternate   = 0;
  126.  
  127.     zerofill    = ' ';
  128.     width       = 0;
  129.  
  130.     precision   = -1;
  131.  
  132.     longflag    = 0;
  133.     capitals    = 0;
  134.  
  135.     backward    = 0;
  136.  
  137.     prefix      = 0;
  138.  
  139. /* Check for optional flags */
  140.     for ( ; ; ) {
  141.       switch (*fmt) {
  142.       case '-': leftjustify = 1; break;
  143.       case '+': showsign    = 1; break;
  144.       case ' ': blankprefix = 1; break;
  145.       case '#': alternate   = 1; break;
  146.       default:  goto DoneFlags;
  147.       }
  148.       fmt++;
  149.     }
  150. DoneFlags:
  151.  
  152. /* Check for field width */
  153.     OPTIONAL(fmt, '0', zerofill, '0');
  154.     width = integer(&fmt, &args);
  155.  
  156. /* Check for precision */
  157.     if (*fmt == '.') {
  158.       fmt++;
  159.       precision = integer(&fmt, &args);
  160.     }
  161.  
  162. /* Check for longs */
  163.     OPTIONAL(fmt, 'l', longflag, 1);
  164.  
  165. /* Switch through all the format options */
  166.     switch (*fmt) {
  167.  
  168.       case 'X':
  169.     capitals++;
  170.       case 'x':
  171.     radix = 16;
  172.     sign  = 0;
  173.     goto oxud;
  174.  
  175.       case 'u':
  176.     radix = 10;
  177.     sign  = 0;
  178.     goto oxud;
  179.  
  180.       case 'o':
  181.     radix = 8;
  182.     sign  = 0;
  183.     goto oxud;
  184.  
  185.       case 'd':
  186.         radix = 10;
  187.         sign  = 1;
  188.  
  189. oxud:
  190.         backward++;
  191.     vs = shortint = 0;
  192.     if (longflag)
  193.       if (sign) vl = va_arg(args, long);
  194.       else      vl = va_arg(args, unsigned long);
  195.     else
  196.       if (sign) vl = va_arg(args, int);
  197.       else      vl = va_arg(args, unsigned);
  198.     if ((negative = sign && vl < 0) != 0)
  199.       vl = -vl;
  200.     do {
  201. Conversion:    
  202.       if (shortint) {
  203.         c   = (vs % (unsigned short) radix) + '0';
  204.         vs /= (unsigned short) radix;
  205.       }
  206.       else {
  207.         if (vl == (unsigned short) vl) {
  208.           vs = (unsigned short) vl;
  209.           shortint = 1;
  210.           goto Conversion;
  211.         }
  212.         else {
  213.           c  = (int) ((unsigned long) (vl) % radix) + '0';
  214.           vl = (unsigned long) (vl) / radix;
  215.         }
  216.       }
  217.       if (c > '9') {
  218.         c += ('a' - '9' - 1);
  219.         if (capitals)
  220.           c+= ('A' - 'a');
  221.       }
  222.       *p++ = c;
  223.     } while (shortint ? (vs != 0) : (vl != 0));
  224.     if (precision > width) {
  225.       width = precision;
  226.       zerofill = '0';
  227.     }
  228.     if (negative) {
  229.       prefix++;
  230.       *p++ = '-';
  231.     }
  232.     else if (sign) {
  233.       if (showsign) {
  234.         prefix++;
  235.         *p++ = '+';
  236.       }
  237.       else if (blankprefix) {
  238.         prefix++;
  239.         *p++ = ' ';
  240.       }
  241.     }
  242.     if (alternate) {
  243.       if (radix == 8) {
  244.         prefix++;
  245.         *p++ = '0';
  246.       }
  247.       else if (radix == 16) {
  248.         prefix += 2;
  249.         *p++ = capitals ? 'X' : 'x';
  250.             *p++ = '0';
  251.       }
  252.     }
  253.     break;
  254.  
  255. /* Single character format */
  256.       case 'c':
  257.     if ((*p++ = va_arg(args, int)) == '\n')
  258.       flush = 1;
  259.     break;
  260.  
  261. /* String format */
  262.       case 's':
  263.     if ((q = va_arg(args, char *)) == NULL)
  264.       q = "(null)";
  265.     p = q;
  266.     if (precision > 0) {
  267.       UNROLL_DO(dostring, precision,
  268.                 if (*p == 0) break;
  269.             if (*p++ == '\n') flush = 1);
  270.     }
  271.     else if (precision < 0) {
  272.       for ( ; ; ) {
  273.         if (*p == 0) break;
  274.         if (*p++ == '\n') flush = 1;
  275.       }
  276.     }
  277.     break;
  278.  
  279. /* Default just print it */
  280.       default:
  281.     if ((*p++ = *fmt) == '\n')
  282.       flush = 1;
  283.     break;
  284.     }
  285.  
  286. /* Scan past conversion character */
  287.     fmt++;
  288.  
  289. /* Length of string to be printed */
  290.     length = p - q;
  291.  
  292. /* Subtract to find padding required */
  293.     if ((width -= length) < 0)
  294.       width = 0;
  295.  
  296. /* Signal left justification */
  297.     if (leftjustify == 0)
  298.       width = -width;
  299.  
  300. /* Check for left justification */
  301.     if (width < 0) {
  302.  
  303. /* Check for negative and zero fill */
  304.       if (zerofill == '0') {
  305.     if (prefix != 0) {
  306.       bytes  += prefix;
  307.       length -= prefix;
  308.       UNROLL_DO(doprefix, prefix, PUTC(backward ? *--p : *q++, fp));
  309.     }
  310.       }
  311.  
  312. /* Now output the rest of the padding */
  313.       width = -width;
  314.       bytes += width;
  315.       UNROLL_DO(doleft, width, PUTC(zerofill, fp));
  316.     }
  317.  
  318. /* Output the string proper */
  319.     if (length > 0) {
  320.       bytes += length;
  321.       UNROLL_DO(dooutput, length, PUTC(backward ? *--p : *q++, fp));
  322.     }
  323.  
  324. /* Do right padding */
  325.     if (width != 0) {
  326.       bytes += width;
  327.       UNROLL_DO(doright, width, PUTC(' ', fp));
  328.     }
  329.   }
  330.  
  331. /* Flush line buffered streams */
  332.     if (flush && TESTFLAG(fp, _IOLBF))
  333.       (void) fflush(fp);
  334.  
  335.   return ferror(fp) ? EOF : bytes;
  336. }
  337.